<?php

namespace beObject\Primitive;

use beObject\Object;
use beObject\Primitive\Boolean;
use beObject\Exceptions\IllegalArgumentException;

/**
 * Object used to represent a char.
 * @author Dany Mottier
 * @copyright MD Consult
 * @license http://www.gnu.org/licenses/gpl.html
 * @link http://www.beobject-framework.net/beobject/primary/char/char-class/<br />
 * @package beObject\Primitive
 * @version 3.0
 */
class Char
    extends Object {

  /** @var char Internam char value. */
  private $char;

  /**
   * Stores the char value in the inner private property.
   * @param type $char The char value.
   * @throws beObject\Exceptions\IllegalArgumentException if $char value is not a char.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-__construct/<br />
   */
  public function __construct($char) {
    if (is_string($char) && strlen($char) == 1) {
      $this->char = $char;
    } else {
      throw new IllegalArgumentException("\$char parameter must be a char.");
    }
  }

  /**
   * Checks if the internal char value equals the char value of the
   * $char parameter.
   * @param \beObject\Primitive\Char $char The char to compare to.
   * @return \beObject\Primitive\Boolean True on succes, false on failure.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-equals/
   */
  public function equals(Char $char = null) {
    if ($this->char == $char()) {
      return new Boolean(true);
    } else {
      return new Boolean(false);
    }
  }

  /**
   * Returns the inner private property when the object is called like a method.
   * @return char The inner private property value.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-__invoke/
   */
  public final function __invoke() {
    return $this->char;
  }

  /**
   * Returns the string representation of the inner private property when the
   * object is printed whit the 'echo' or 'print' directive.
   * @return string Returns The char value.
   * @link http://www.beobject-framework.net/beobject/primary/char/char__tostring/
   */
  public function __toString() {
    return $this->char;
  }

  /**
   * Defines if the char is a digit or not.
   * @return \beObject\Primitive\Boolean Returns true if the char is a digit,
   * false otherwise.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-isdigit/
   */
  public function isDigit() {
    $return = false;
    $asciiValue = ord($this->char);

    if (($asciiValue > 47 && $asciiValue < 58) ||
        ($asciiValue > 97 && $asciiValue < 122)) {
      $return = true;
    }
    return new Boolean($return);
  }

  /**
   * Defines if the char is a letter or not.
   * @return \beObject\Primitive\Boolean Returns true if the char is a letter,
   * false otherwise.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-isletter/
   */
  public function isLetter() {
    $return = false;
    $asciiValue = ord($this->char);

    if (($asciiValue > 65 && $asciiValue < 90) ||
        ($asciiValue > 96 && $asciiValue < 123)) {
      $return = true;
    }
    return new Boolean($return);
  }

  /**
   * Defines if the char is a letter or a digit, or not.
   * @return \beObject\Primitive\Boolean Returns true if the char is a letter
   * or a digit, false otherwise.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-isletterordigit/
   */
  public function isLetterOrDigit() {
    $return = false;
    if ($this->isDigit()->booleanValue() || $this->isLetter()->booleanValue()) {
      $return = true;
    }
    return new Boolean($return);
  }

  /**
   * Defines if the char is lower case or not.
   * @return beObject\Primitive\Boolean True if the char is lower case,
   * false otherwise.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-islower/
   */
  public function isLower() {
    $return = false;
    $asciiValue = ord($this->char);

    if ($asciiValue > 96 && $asciiValue < 123) {
      $return = true;
    }
    return new Boolean($return);
  }

  /**
   * Defines if the char is a punctuation char or not.<br />
   * Punctuation char are :
   * <ul>
   * <li></li>
   * <li></li>
   * <li></li>
   * <li></li>
   * <li></li>
   * </ul>
   * @return beObject\Primitive\Boolean True if the char is a unctuation,
   * false otherwise.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-ispunctuation/
   */
  public function isPunctuation() {
    $return = false;
    $asciiValue = ord($this->char);

    if ($asciiValue == 33 || $asciiValue == 46 ||
        $asciiValue == 58 || $asciiValue == 59 ||
        $asciiValue == 63) {
      $return = true;
    }
    return new Boolean($return);
  }

  /**
   * Defines if the char is upper case or not.
   * @return beObject\Primitive\Boolean True if the char is upper case,
   * false otherwise.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-isupper/
   */
  public function isUpper() {
    $return = false;
    $asciiValue = ord($this->char);

    if ($asciiValue > 64 && $asciiValue < 91) {
      $return = true;
    }
    return new Boolean($return);
  }

  /**
   * Defines if the char is a white space or not.
   * @return beObject\Primitive\Boolean True if the char is a white space,
   * false otherwise.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-iswhitespace/
   */
  public final function isWhiteSpace() {
    $return = false;
    if (ord($this->char) == 32) {
      $return = true;
    }
    return new Boolean($return);
  }

  /**
   * Parse any object to a char.
   * @param mixed $char The variable to parse as a char.
   * @return beObject\Primitive\Char The parsed char.
   * @throws beObject\Exceptions\IllegalArgumentException if the given variable
   * could not be parsed to a char.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-parse/<br />
   */
  public static function parse($char) {
    $innerChar = '';

    switch (gettype($char)) {
      case "string" :
        if (strlen($char) == 1) {
          $innerChar = $char;
        }
        break;
      case "object" :
        switch (get_class($char)) {
          case "beObject\Primitive\Char" :
            $innerChar = $char();
            break;
          case "beObject\Primitive\String" :
            if ($char->length()->integerValue() == 1) {
              $innerChar = $char();
            }
            break;
          case "beObject\Primitive\Integer" :
            if ($char() >= 0 && $char() <= 9) {
              $innerChar = $char->toString();
            }
            break;
        }
    }

    if ($innerChar != '') {
      return new Char($innerChar);
    } else {
      throw new IllegalArgumentException("Can not parse parameter to a char");
    }
  }

  /**
   * Makes the char lower case.
   * @return \beObject\Primitive\Char The char lower case.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-tolower/
   */
  public function toLower() {
    return new Char(strtolower($this->char));
  }

  /**
   * Returns the char.
   * @return string The inner property value.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-tostring/
   */
  public function toString() {
    return $this->char;
  }

  /**
   * Makes the char upper case.
   * @return \beObject\Primitive\Char The char upper case.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-toupper/
   */
  public function toUpper() {
    return new Char(strtoupper($this->char));
  }

  /**
   * Returns the char value.
   * @return char The char value.
   * @link http://www.beobject-framework.net/beobject/primary/char/char-charvalue/
   */
  public final function charValue() {
    return $this->char;
  }

}

?>
